package com.guli.mall.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guli.common.constant.AuthServerConstant;
import com.guli.common.constant.MemberConstant;
import com.guli.common.constant.ProtocolEnum;
import com.guli.common.pojo.vo.StatusCodeEnum;
import com.guli.common.utils.HttpUtils;
import com.guli.mall.member.entity.MemberLevelEntity;
import com.guli.mall.member.service.MemberLevelService;
import com.guli.mall.member.vo.WeiBoUserInfoVo;
import com.guli.mall.serviceBase.globalException.MallException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.Pattern;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guli.common.utils.PageUtils;
import com.guli.common.utils.Query;

import com.guli.mall.member.mapper.MemberMapper;
import com.guli.mall.member.entity.MemberEntity;
import com.guli.mall.member.service.MemberService;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;


@Service("memberService")
@Slf4j
public class MemberServiceImpl extends ServiceImpl<MemberMapper, MemberEntity> implements MemberService {

    @Resource
    ExecutorService executorService;

    @Resource
    MemberLevelService memberLevelService;

    private static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();

    private static final TypeReference<WeiBoUserInfoVo> TYPE_REFERENCE_WEI_BO_USER_VO = new TypeReference<WeiBoUserInfoVo>() {
    };

    @Override
    public PageUtils<MemberEntity> queryPage(Integer currentPage, Integer size, Map<String, Object> params) {

        Page<MemberEntity> page = new Page<>(currentPage, size);

        Page<MemberEntity> resultPage = this.page(page);


        return new PageUtils<>(resultPage);
    }

    @Override
    public void checkRepeatAndSave(MemberEntity member) throws Exception {

        CompletableFuture<MemberLevelEntity> getDefaultMemberLevelTask = CompletableFuture.supplyAsync(() -> {

            return memberLevelService.getDefaultMemberLevel();

        }, executorService);


        CompletableFuture<Integer> checkUserNameRepeatTask = CompletableFuture.supplyAsync(() -> {

            return getMemberNumberByAttr("username", member.getUsername());

        }, executorService);


        CompletableFuture<Void> insertTask = CompletableFuture.supplyAsync(() -> {

            return getMemberNumberByAttr("mobile", member.getMobile());

        }, executorService).thenAcceptBoth(checkUserNameRepeatTask, (userNameCount, phoneNumberCount) -> {
            if (userNameCount > 0) {
                throw new MallException(StatusCodeEnum.USERNAME_ALREADY_EXIST);
            }

            if (phoneNumberCount > 0) {
                throw new MallException(StatusCodeEnum.PHONE_NUMBER_ALREADY_REGISTERED);
            }

            try {
                MemberLevelEntity memberLevelEntity = getDefaultMemberLevelTask.get(1, TimeUnit.SECONDS);

                member.setLevelId(memberLevelEntity.getId());

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }

            // 对密码进行加密（同时加盐）
            member.setPassword(PASSWORD_ENCODER.encode(member.getPassword()));

            log.info("phoneNumber = {}，userName = {}，都没有重复，准备添加到数据库", member.getMobile(), member.getUsername());

            this.save(member);

        });
        try {
            insertTask.get();
        } catch (ExecutionException e) {

            throw e.getCause() instanceof MallException ? (MallException) e.getCause() : e;
        }
    }

    @Override
    public MemberEntity login(MemberEntity memberEntity) {

        QueryWrapper<MemberEntity> wrapper = new QueryWrapper<>();



        /*if(Pattern.matches(AuthServerConstant.PHONE_NUMBER_REGEX,memberEntity.getMobile())){

        }*/

        wrapper.eq("username", memberEntity.getUsername()).or().eq("mobile", memberEntity.getUsername());

        MemberEntity member = this.getOne(wrapper);

        if (ObjectUtils.isEmpty(member)) {
            //1、用户名不存在
            throw new MallException(StatusCodeEnum.USERNAME_OR_PASSWORD_NOT_CORRECT);
        }

        if (!PASSWORD_ENCODER.matches(memberEntity.getPassword(), member.getPassword())) {
            //2、密码错误
            throw new MallException(StatusCodeEnum.USERNAME_OR_PASSWORD_NOT_CORRECT);
        }

        member.setPassword(null); //清空密码

        return member;
    }

    @Override
    public MemberEntity loginFromWeiBoUid(MemberEntity memberEntityFromWeiBo) {

        QueryWrapper<MemberEntity> wrapper = new QueryWrapper<>();

        wrapper.eq("wei_bo_uid", memberEntityFromWeiBo.getWeiBoUid());

        MemberEntity memberEntityAlreadyInDB = this.getOne(wrapper);

        if (ObjectUtils.isEmpty(memberEntityAlreadyInDB)) {
            // 为用户生成一个账户

            MemberEntity memberEntity = new MemberEntity();

            memberEntity.setWeiBoUid(memberEntityFromWeiBo.getWeiBoUid());

            memberEntity.setExpiresIn(memberEntityFromWeiBo.getExpiresIn());

            memberEntity.setWeiBoAccessToken(memberEntityFromWeiBo.getWeiBoAccessToken());


            Map<String, Object> weiBoUserInfoOfUser = this.getWeiBoUserInfoOfUser(memberEntity);

            if(!ObjectUtils.isEmpty(weiBoUserInfoOfUser)){

                String userName = ObjectUtils.isEmpty(weiBoUserInfoOfUser.get("screen_name")) ? null : weiBoUserInfoOfUser.get("screen_name").toString();

                // 设置用户的微博昵称作为用户昵称
                memberEntity.setNickname(userName);

                memberEntity.setUsername(userName);

                memberEntity.setGender(
                        ObjectUtils.isEmpty(weiBoUserInfoOfUser.get("gender")) ? null : weiBoUserInfoOfUser.get("gender").toString().equals("m") ? MemberConstant.MALE : MemberConstant.FEMALE);
            }


            this.save(memberEntity);

            return memberEntity;
        }

        MemberEntity member = new MemberEntity();

        BeanUtils.copyProperties(memberEntityFromWeiBo, member);

        member.setId(memberEntityAlreadyInDB.getId());

        memberEntityAlreadyInDB.setWeiBoAccessToken(memberEntityFromWeiBo.getWeiBoAccessToken());

        memberEntityAlreadyInDB.setExpiresIn(memberEntityFromWeiBo.getExpiresIn());

        memberEntityAlreadyInDB.setPassword(null);

        CompletableFuture.runAsync(() -> {
            this.updateById(member); // 更新accessToken 和 expiresIn
        }, executorService);

        return memberEntityAlreadyInDB;
    }

    @Override
    public Map<String, Object> getWeiBoUserInfoOfUser(MemberEntity memberEntity) {

        List<NameValuePair> params = new ArrayList<>();

        params.add(new BasicNameValuePair("access_token", memberEntity.getWeiBoAccessToken()));
        params.add(new BasicNameValuePair("uid", memberEntity.getWeiBoUid()));

        JSONObject jsonObject = null;
        try {
            HttpResponse httpResponse = HttpUtils.get(ProtocolEnum.HTTPS, "api.weibo.com", "/2/users/show.json", params);

            String entityJson = EntityUtils.toString(httpResponse.getEntity());

            if (httpResponse.getStatusLine().getStatusCode() != 200) {
                log.warn("获取用户 uid = {}，微博信息失败，接收到的参数是：{}", memberEntity.getWeiBoUid(), entityJson);
                return null;
            }


            // WeiBoUserInfoVo weiBoUserInfoVo = JSON.parseObject(entityJson, TYPE_REFERENCE_WEI_BO_USER_VO); 解析异常

            jsonObject = JSON.parseObject(entityJson);

            Object screen_name = jsonObject.get("screen_name");
            // TODO 在这里可以获取微博账户的大部分个人信息
            log.info("新注册的uid = {}的微博用户的昵称是：{}", memberEntity.getWeiBoUid(), screen_name.toString());
            //System.out.println("微博用户的信息是：" + weiBoUserInfoVo.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return jsonObject;
    }


    public Integer getMemberNumberByAttr(String mobile, String mobile2) {
        QueryWrapper<MemberEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(mobile, mobile2);
        return this.count(wrapper);
    }


}